﻿using DotNetCore.CAP;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using System.Transactions;
using X23.Application.ExcelManagement;
using X23.Application.NotificationManagement;
using X23.Application.UserManagement;
using X23.Application.UserManagement.Dto;
using X23.Extensions.AttributeExtensions;
using X23.Model.User;
using X23.Util.LinqUtil;

namespace X23.Controllers
{
    /// <summary>
    /// 用户管理
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class UserController : BaseApiController
    {
        private readonly ICapPublisher _capPublisher;
        private readonly IServiceProvider _serviceProvider;
        private readonly IUserManagementService _userManagementService;
        private readonly IExcelManagementService _excelManagementService;
        private readonly INotificationManagementService _notificationManagementService;

        public UserController(
            ICapPublisher capPublisher,
            IServiceProvider serviceProvider,
            IUserManagementService userManagementService,
            IExcelManagementService excelManagementService,
            INotificationManagementService notificationManagementService
            )
        {
            _capPublisher = capPublisher;
            _serviceProvider = serviceProvider;
            _userManagementService = userManagementService;
            _excelManagementService = excelManagementService;
            _notificationManagementService = notificationManagementService;
        }


        [HttpPost]
        [AllowAnonymous]
        public async Task TestAAA(QueryDto input)
        {
            Assembly asm = Assembly.Load("X23");//FullPath 为Dll所在位置的全路径。
            Type t = asm.GetType("X23.Controllers.UserController");//命名空间名.类名
            //object oaaa = Activator.CreateInstance(t); //创建Type t类型的对象
            var obj = Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, t);//通过ActivatorUtilities实例化对象
            //var methodData22 = t.GetMethod(method).Invoke(obj, parameters);

            var methodData = obj.GetType().GetMethod("QueryData").Invoke(obj, new[] { input });
            object o = methodData;
            if (o is Task)
            {
                var task = methodData as Task;
                await task;
                o = task.GetType().GetProperty("Result").GetValue(task, null);
            }
        }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<UserDto> GetCurrentUser()
        {
            return await Task.FromResult(CurrentUser);
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<UserInfoDto> Login(LoginUserDto userDto)
        {
            return await _userManagementService.Login(userDto);
        }

        /// <summary>
        /// 微信登陆
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<UserInfoDto> LoginByWeChat(string code)
        {
            return await _userManagementService.LoginByWeChat(code);
        }

        #region 消息通知测试
        [HttpGet]
        public async Task SendAll()
        {
            var obj = new
            {
                User = CurrentUser.Id,
                Msg = $"Hello : {DateTime.UtcNow.AddHours(8)}"
            };
            await _notificationManagementService.SendAll("Notify", obj);
        }
        [HttpGet]
        public async Task SendUser(string userId, string msg)
        {
            userId = string.IsNullOrEmpty(userId) ? CurrentUser.Id.ToString() : userId;
            await _notificationManagementService.SendUser(userId, "Notify", $"给指定用户{userId}发消息:{msg}");
        }
        [HttpGet]
        public async Task SendGroup(string groupName, string msg)
        {
            await _notificationManagementService.SendGroup(groupName, "Notify", $"给指定组{groupName}发消息:{msg}");
        }
        #endregion

        #region 导入
        /// <summary>
        /// 用户导入
        /// </summary>
        /// <param name="taskPerformanceId">任务Id</param>
        /// <returns></returns>
        [HttpPost]
        [UnitOfWork(IsDisabled = true)]
        public async Task UserImport(int taskPerformanceId)
        {
            var task = await _excelManagementService.GetTaskPerformance(taskPerformanceId);
            if (task.TaskExeStatus == Model.Const.Enum.TaskExeStatus.Success)
            {
                var data = await _excelManagementService.ConvertExcelToData<UserDto>(taskPerformanceId);
                foreach (var item in data)
                {
                    try
                    {
                        //不参与事物
                        using (TransactionScope scope1 = new TransactionScope(TransactionScopeOption.Suppress))
                        {
                            await _userManagementService.AddAsync(item);
                        }
                    }
                    catch (Exception)
                    {
                        //todo 捕捉错误信息汇报
                    }
                }
            }
            else
            {
                throw new Exception("该任务未成功！");
            }
        }
        #endregion

        #region 导出
        /// <summary>
        /// 导出
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<int> UserExport(Application.ExcelManagement.Dto.ExportCapDto<QueryDto> exportCapDto)
        {
            var input = exportCapDto.QueryInput;
            var fileName = input.FileName + ".xlsx";
            var exportTask = await _excelManagementService.GetExportTask(new Application.ExcelManagement.Dto.ExportDto
            {
                Code = "/User",
                FileName = fileName,
                IsCap = exportCapDto.IsCap
            });
            var capDto = new Application.ExcelManagement.Dto.ExportCapDto<QueryDto>
            {
                QueryInput = input,
                TaskPerformanceId = exportTask.Id
            };
            if (exportCapDto.IsCap)
            {
                _capPublisher.Publish("UserExportCapMethod", capDto);
            }
            else
            {
                await UserExportCapMethod(capDto);
            }
            return exportTask.Id;
        }

        [HttpPost]
        [CapSubscribe("UserExportCapMethod")]
        public async Task UserExportCapMethod(Application.ExcelManagement.Dto.ExportCapDto<QueryDto> capDto)
        {
            await _excelManagementService.Export(capDto.QueryInput, QueryData, capDto.TaskPerformanceId);
        }
        #endregion

        #region CRUD
        /// <summary>
        /// 查询用户列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageData<UserDto>> QueryData(QueryDto input)
        {
            //写这么复杂是为了验证拼接Expression
            Expression<Func<User, bool>> predicate = x => true;
            predicate = predicate.And(x => string.IsNullOrEmpty(input.Name) || x.Name.Contains(input.Name));
            predicate = predicate.And(x => string.IsNullOrEmpty(input.Account) || x.Account.Contains(input.Account));

            var result = await _userManagementService.GetPageDataAsync(predicate, input.Pages, input.Rows);

            var pageUserIds = result.Data.Select(x => x.Id).ToList();
            var roleItem = await _userManagementService.GetUserRoleList(x => pageUserIds.Contains(x.UserId));
            
            //填充
            result.Data.ForEach(item =>
            {
                item.RoleDtoList = roleItem.Where(x => x.UserId == item.Id).Select(x => new Application.RoleManagement.Dto.RoleDto { Id = x.RoleId, Name = x.RoleName }).OrderBy(x => x.Id).ToList();
                item.RoleIds = item.RoleDtoList.Select(x => x.Id).ToList();
            });
            return result;
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="userPasswordDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> UpdatePassword(UserPasswordDto userPasswordDto)
        {
            var user = CurrentUser;
            if (user.Account=="admin")
            {
                throw new Exception("管理员不可修改密码！");
            }
            return await _userManagementService.UpdatePassword(user.Id, userPasswordDto.OldPassword, userPasswordDto.NewPassword);
        }
        /// <summary>
        /// 添加或者修改用户信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> AddOrUpdate(UserDto user)
        {
            return await _userManagementService.AddOrUpdateUser(user);
        }
        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<UserDto> Add(UserDto user)
        {
            return await _userManagementService.AddAsync(user);
        }
        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<UserDto> Update(UserDto user)
        {
            return await _userManagementService.UpdateAsync(user);
        }
        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<bool> Delete(int userId)
        {
            if (userId == CurrentUser.Id)
            {
                throw new Exception("不能删除自己！");
            }
            var user = await _userManagementService.GetByIdAsync(userId);
            if (user.Account == "admin")
            {
                throw new Exception("不能删除管理员账号！");
            }
            return await _userManagementService.DeleteUserAndUserRole(userId);
        }
        #endregion

        #region Test
        /// <summary>
        /// 测试 通过userId获取用户信息
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<string> Test(int userId)
        {
            return await _userManagementService.Test(userId);
        }

        /// <summary>
        /// 测试工作单元
        /// </summary>
        /// <param name="isError">this is my error</param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task TestUnitOfWork(bool isError)
        {
            await _userManagementService.AddAsync(new UserDto { Name = "1" });
            await _userManagementService.AddAsync(new UserDto { Name = "2" });
            if (isError)
            {
                throw new System.Exception("this is my error");
            }
            await _userManagementService.AddAsync(new UserDto { Name = "3" });
        }
        /// <summary>
        /// 测试禁用的工作单元
        /// </summary>
        /// <param name="isError">this is my error</param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        [UnitOfWork(IsDisabled = true)]
        public async Task TestUnitOfWorkByDisabled(bool isError)
        {
            await _userManagementService.AddAsync(new UserDto { Name = "1" });
            await _userManagementService.AddAsync(new UserDto { Name = "2" });
            if (isError)
            {
                throw new System.Exception("this is my error");
            }
            await _userManagementService.AddAsync(new UserDto { Name = "3" });
        }
        #endregion
    }
}
